package de.godlike.services.internal;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.log4j.Logger;

import de.godlike.services.internal.dataTypes.DiskInfo;
import de.godlike.services.internal.dataTypes.WinProcess;

/**
 * This class offers some information and methods to access the system. It only
 * works for Windows-OS.
 * 
 * @author asmodaeus
 * 
 */
public class SysAccessWin {

	private final Logger logger = Logger.getLogger(SysAccessWin.class);

	/**
	 * shutdown the system!
	 * 
	 * @param seconds2Live
	 *            seconds, until the system goes down (0 = now!)
	 */
	public void shutdown(int seconds2Live) {
		try {
			new ProcessBuilder("shutdown", "-s", "-t",
					String.valueOf(seconds2Live)).start();
		} catch (IOException e) {
			this.logger.error("shutdown error: " + e.getMessage(), e);
		}
	}

	/**
	 * restart the system
	 */
	public void restart() {
		try {
			new ProcessBuilder("shutdown", "-r").start();
		} catch (IOException e) {
			this.logger.error("restart error: " + e.getMessage(), e);
		}
	}

	/**
	 * @return a list of all running processes
	 */
	public List<WinProcess> tasklist() {
		List<WinProcess> processList = new ArrayList<WinProcess>();
		try {
			Process proc = new ProcessBuilder("tasklist", "/FO", "CSV").start();

			Scanner s = new Scanner(proc.getInputStream())
					.useDelimiter("[,\\r\\n]");
			WinProcess currProc = new WinProcess();
			int i = 1;
			int j = 1;
			while (s.hasNext()) {
				String currString = s.next();
				if (!currString.equals("")) {
					currString = currString.substring(1,
							currString.length() - 1);
					if ((i % 5 == 1) && (j > 5)) {
						currProc.setName(currString);
					}
					if ((i % 5 == 2) && (j > 5)) {
						currProc.setPid(Integer.valueOf(currString));
					}
					if (i % 5 == 0) {
						i = 0;
					}
					if ((i % 5 == 0) && (j > 5)) {
						currProc.setMemUse(currString);
						processList.add(currProc);
						currProc = new WinProcess();
					}
					i++;
					j++;
				}
			}
		} catch (IOException e) {
			this.logger.error("tasklist error: " + e.getMessage(), e);
		}
		return processList;
	}

	/**
	 * Kills a process with the passed pid.
	 * 
	 * @param pid
	 *            process id of the process 2 kill.
	 * @return whether the process could be killed.
	 */
	public boolean taskkill(int pid) {
		try {
			Process proc = new ProcessBuilder("taskkill", "/PID",
					String.valueOf(pid)).start();
			if (proc.waitFor() != 0) {
				return false;
			} else {
				return true;
			}
		} catch (IOException e) {
			this.logger.error("taskkill error: " + e.getMessage(), e);
		} catch (InterruptedException e) {
			this.logger.error("taskkill error: " + e.getMessage(), e);
		}
		return false;
	}

	/**
	 * @return the list of all Disks known in the OS with infos like
	 *         total/used/free Space.
	 */
	public List<DiskInfo> getDiskList() {
		List<DiskInfo> returnList = new ArrayList<DiskInfo>();

		for (File file : File.listRoots()) {
			DiskInfo tmpDisk = new DiskInfo();
			tmpDisk.setMountPoint(file.getAbsolutePath());
			tmpDisk.setUsedSpace(String.valueOf((file.getTotalSpace() - file
					.getFreeSpace()) / 1024));
			tmpDisk.setFreeSpace(String.valueOf(file.getFreeSpace() / 1024));
			tmpDisk.setTotalSpace(String.valueOf(file.getTotalSpace() / 1024));

			returnList.add(tmpDisk);
			tmpDisk = null;
		}

		return returnList;
	}

	/**
	 * @deprecated Just 4 test!
	 * @param args
	 */
	@Deprecated
	public static void main(String[] args) {
		// new SysAccessWin().tasklist();
		// new SysAccessWin().taskkill(284);
		List<DiskInfo> bla = new SysAccessWin().getDiskList();
		for (DiskInfo diskInfo : bla) {
			System.out.println(diskInfo);
		}
	}
}
